package com.hq.ims.userpc.busservice;

import com.hq.authority.utils.AppUtils;
import com.hq.ims.data.entity.*;
import com.hq.ims.data.entityenum.EnumAuditStatus;
import com.hq.ims.data.entityenum.EnumCompanyUpdateType;
import com.hq.ims.data.entityenum.EnumMenuOwnType;
import com.hq.ims.data.event.CompanyEvent;
import com.hq.ims.data.service.*;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.utils.LocalConstant;
import com.hq.ims.data.utils.WebExpandUtils;
import com.hq.ims.data.vo.*;
import com.hq.utils.exception.CommonException;
import com.hq.utils.util.*;
import com.hq.web.utils.SpringBootValidateUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class UserPcMyInfoBusService {

    @Resource
    private BasePermissionMenuService basePermissionMenuService;
    @Resource
    private BaseUserService baseUserService;
    @Resource
    private BaseCompanyEmployeeService baseCompanyEmployeeService;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private BaseCompanyDepartmentEmployeeService baseCompanyDepartmentEmployeeService;
    @Resource
    private BaseCompanyDepartmentService baseCompanyDepartmentService;
    @Resource
    private BaseCompanyCheckService baseCompanyCheckService;
    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private BaseCompanyChangeHistoryService baseCompanyChangeHistoryService;
    @Resource
    private BasePermissionMapRoleUserService basePermissionMapRoleUserService;

    public List<PermissionMenuMapstruct.PermissionMenuTreeVo> getHaveAuthMenu(
    ) {
        String userId = AppUtils.getUserId();
        String companyId = WebExpandUtils.getHeadCompanyId();
        StringUtils.verificationEmpty(userId, ErrMsgConstant.USER_INFO_NOT_EXISTS);
        List<PermissionMenuMapstruct.PermissionMenuTreeVo> sysMenuTreeVo = basePermissionMenuService.getTreeByUserIdAndCompanyId(userId, companyId, EnumMenuOwnType.User);
        return sysMenuTreeVo;
    }

    /**
     * 获取当前tokenUser信息
     */
    public UserMapstruct.UserAndCompanySimpleVo getMyInfo(
    ) {
        String userId = AppUtils.getUserId();
        User curUserInfo = baseUserService.getById(userId);
        ObjectUtils.isNullThrow(curUserInfo, ErrMsgConstant.USER_INFO_NOT_EXISTS);

        //当前用户在哪家公司任职
        List<CompanyEmployee> companyEmployeeList = baseCompanyEmployeeService.lambdaQuery()
                .eq(CompanyEmployee::getUserId, userId)
                .orderByAsc(CompanyEmployee::getCreateDateTime)
                .list();
        ListUtils.isNotExistsEleTh(companyEmployeeList, ErrMsgConstant.USER_UN_JOIN_COMPANY);

        //公司员工
        CompanyEmployee companyEmployee = companyEmployeeList.get(0);
        ObjectUtils.isNullThrow(companyEmployee, ErrMsgConstant.USER_UN_JOIN_COMPANY);

        //查找用户公司
        Company company = baseCompanyService.getById(companyEmployee.getCompanyId());
        ObjectUtils.isNullThrow(companyEmployee, ErrMsgConstant.COMPANY_INFO_NOT_EXISTS);

        //先组装简单对象
        UserMapstruct.UserAndCompanySimpleVo curUerSimpleInfo = new UserMapstruct.UserAndCompanySimpleVo();
        curUerSimpleInfo.setUserId(userId);
        curUerSimpleInfo.setRealName(curUserInfo.getRealName());
        curUerSimpleInfo.setAvatarUrl(curUserInfo.getAvatarUrl());
        curUerSimpleInfo.setAccountStatus(curUserInfo.getAccountStatus());
        curUerSimpleInfo.setSex(curUserInfo.getSex());
        curUerSimpleInfo.setMobile(curUserInfo.getMobile());
        curUerSimpleInfo.setRegisterTime(curUserInfo.getCreateDateTime());

        curUerSimpleInfo.setCompanyId(company.getCompanyId());
        curUerSimpleInfo.setCompanyName(company.getCompanyName());
        curUerSimpleInfo.setCompanyLevel(company.getCompanyLevel());

        //查找用户部门,可能不存在部门
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = baseCompanyDepartmentEmployeeService.getByUserIdAndDepartmentId(userId, company.getCompanyId());
        if (ListUtils.isExistsEle(companyDepartmentEmployeeList)) {
            ListUtils.sortInt(companyDepartmentEmployeeList, d -> d.getIsPartTimeJob() ? 1 : 0, true);
            CompanyDepartmentEmployee companyDepartmentEmployee = companyDepartmentEmployeeList.get(0);
            CompanyDepartment companyDepartment = baseCompanyDepartmentService.getById(companyDepartmentEmployee.getCompanyDepartmentId());
            curUerSimpleInfo.setCompanyDepartmentId(companyDepartment.getCompanyDepartmentId());
            curUerSimpleInfo.setCompanyDepartmentName(companyDepartment.getCompanyDepartmentName());
            curUerSimpleInfo.setIsCompanyDepartmentPrincipal(companyDepartmentEmployee.getIsPrincipal());
            curUerSimpleInfo.setJobName(companyDepartmentEmployee.getJobName());
            curUerSimpleInfo.setIsCompanyAdmin(companyEmployee.getIsAdmin());
        }
        return curUerSimpleInfo;
    }

    /**
     * 获取登陆后状态
     */
    public UserMapstruct.LoginSuccessAfterReturnStatus getLoginAfterStatus(
            String userId,
            String companyId
    ) {
        UserMapstruct.LoginSuccessAfterReturnStatus loginSuccessAfterReturnStatus = new UserMapstruct.LoginSuccessAfterReturnStatus();
        loginSuccessAfterReturnStatus.setNewCompanyAuditing(false);
        loginSuccessAfterReturnStatus.setExistsNewCompanyAuditPass(false);
        loginSuccessAfterReturnStatus.setExistsNewCompanyAuditNotPass(false);
        loginSuccessAfterReturnStatus.setExistsTodoDistributionRole(false);
        loginSuccessAfterReturnStatus.setExistsUnJoinCompany(false);
        loginSuccessAfterReturnStatus.setExistsNewCompanyCancelAudit(false);

        if (StringUtils.isEmpty(companyId)) {
            //如果公司ID不为空那肯定是未加入公司
            loginSuccessAfterReturnStatus.setExistsUnJoinCompany(true);
        } else {
            //已加入公司
            //获取公司审核信息并且是新公司
            boolean firstNewCompany = baseCompanyService.isFirstNewCompany(companyId);
            Company company = baseCompanyService.getById(companyId);
            //作为新公司 -审核中
            loginSuccessAfterReturnStatus.setNewCompanyAuditing(firstNewCompany && company.getAuditStatus() == EnumAuditStatus.UnderReview);
            //作为新公司 - 通过审核
            loginSuccessAfterReturnStatus.setExistsNewCompanyAuditPass(firstNewCompany && company.getAuditStatus() == EnumAuditStatus.Pass);
            //作为新公司 - 审核拒绝
            loginSuccessAfterReturnStatus.setExistsNewCompanyAuditNotPass(firstNewCompany && company.getAuditStatus() == EnumAuditStatus.NotPass);
            //作为新公司 - 主动撤回
            loginSuccessAfterReturnStatus.setExistsNewCompanyCancelAudit(firstNewCompany && company.getAuditStatus() == EnumAuditStatus.CancelAudit);
            //加入公司但未分配部门

            List<CompanyEmployee> companyEmployeeList = baseCompanyEmployeeService.getByUserIdAndCompanyId(userId, companyId, null);
//            List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = baseCompanyDepartmentEmployeeService.getByUserIdAndCompanyId(userId, companyId, null);
            List<PermissionMapRoleUser> permissionMapRoleUserList = basePermissionMapRoleUserService.getByUserIdAndCompanyId(userId, companyId);
            boolean isCompanyAdmin = false;
            if (ListUtils.isExistsEle(companyEmployeeList)) {
                isCompanyAdmin = companyEmployeeList.stream().filter(d -> d.getIsAdmin()).count() > 0;
            }
            //加入(部门/公司)但未分配角色,并且不是管理员
            loginSuccessAfterReturnStatus.setExistsTodoDistributionRole(!isCompanyAdmin && ListUtils.isNotExistsEle(permissionMapRoleUserList) && ListUtils.isExistsEle(companyEmployeeList));

            //用户被移除
            loginSuccessAfterReturnStatus.setExistsUnJoinCompany(ListUtils.isNotExistsEle(companyEmployeeList));
        }
        return loginSuccessAfterReturnStatus;
    }

    /**
     * 我的企业信息
     *
     * @param companyVo
     * @return
     */
    public CompanyMapstruct.CompanyVo myCompanyInfo(CompanyMapstruct.CompanyVo companyVo) {

//        String userId = AppUtils.getUserId();

        String companyId = WebExpandUtils.getHeadCompanyId();

        if (StringUtils.isEmpty(companyId)){
            throw CommonException.build("当前登录人企业信息为空");
        }

        Company company = baseCompanyService.lambdaQuery().eq(Company::getCompanyId, companyId).one();

        if (company == null) {
            throw CommonException.build("企业信息为空");
        }

        CompanyMapstruct.CompanyVo vo = JsonUtils.convertObject(company, CompanyMapstruct.CompanyVo.class);

        boolean firstCheck = baseCompanyCheckService.isFirstCheck(vo.getCompanyId());

        //未通过
        if (company.getAuditStatus() != EnumAuditStatus.Pass && firstCheck) {

            CompanyMapstruct.CompanyVo vo1 = JsonUtils.convertObject(company, CompanyMapstruct.CompanyVo.class);

            CompanyCheck check = baseCompanyCheckService.getLastCheckByCompanyId(vo1.getCompanyId());
            if (check == null) {
                throw CommonException.build("审核数据已经不存在");
            }
            CompanyCheckMapstruct.CompanyCheckVo companyCheckVo = baseCompanyService.checkCompanyDetail(check);

            vo1.setCompanyAptitudeFiles(JsonUtils.convertListObject(companyCheckVo.getCompanyAptitudeHistoryVos(), CompanyAptitudeMapstruct.CompanyAptitudeVo.class));
            vo1.setCompanyRuleFiles(companyCheckVo.getCompanyRuleFiles().getFiles());
            vo1.setServiceArea(JsonUtils.convertListObject(companyCheckVo.getServiceArea(), CompanyServiceArea.class));
            vo1.setServiceType(JsonUtils.convertListObject(companyCheckVo.getServiceType(), CompanyServiceType.class));
            vo1.setCompanyIdFiles(companyCheckVo.getCompanyIdFiles());
            vo1.setCompanyOffReason(companyCheckVo.getRejectReason());

            return vo1;
        }

        return baseCompanyService.getCompanyDetail(vo);
    }

    public boolean updateCompanyInfo(CompanyMapstruct.CompanyVo companyVo) {

        if (companyVo.getCompanyUpdateType() == null) {
            throw CommonException.build("修改参数数据不全");
        }

        boolean bl = baseCompanyService.updCompanyInfo(companyVo);
        BooleanUtils.isFalseThrow(bl, "修改企业信息失败");


        //查询最新的公司信息
        Company lastNewCompanyData = baseCompanyService.getById(companyVo.getCompanyId());
        //是否公司信息修改
        boolean isCompanyUpdate = false;
        //是否规则修改
        boolean isRuleUpdate = false;
        if (companyVo.getCompanyUpdateType() == EnumCompanyUpdateType.AllUpdate) {
            isCompanyUpdate = true;
            isRuleUpdate = true;
        }
        //基础信息修改
        else if (companyVo.getCompanyUpdateType() == EnumCompanyUpdateType.BaseInfo) {
            isCompanyUpdate = true;
        }
        //收益规则修改
        else if (companyVo.getCompanyUpdateType() == EnumCompanyUpdateType.RuleInfo) {
            isRuleUpdate = true;
        }

        if (isCompanyUpdate) {
            //发布修改公司信息事件
            applicationContext.publishEvent(new CompanyEvent(this, lastNewCompanyData, CompanyEvent.EDIT_COMPANY));
        }
        if (isRuleUpdate) {
            //发布修改分配规则公司信息事件
            applicationContext.publishEvent(new CompanyEvent(this, lastNewCompanyData, CompanyEvent.EDIT_DISTRIBUTION_RULE));
        }

        return bl;
    }

    @Transactional(rollbackFor = Exception.class)
    public void joinCompany(String companyId) {
        String userId = AppUtils.getUserId();
        String headCompanyId = WebExpandUtils.getHeadCompanyId();
        Company company = baseCompanyService.getById(companyId);
        ObjectUtils.isNullThrow(company, ErrMsgConstant.COMPANY_INFO_NOT_EXISTS);

        //验证用户是否已经加入其它公司,如果加入其它公司则需要移除,后再创建新公司
        List<CompanyEmployee> companyEmployeeList = baseCompanyEmployeeService.getByUserId(userId, null);
        List<String> needDelCompanyIdList = new ArrayList<>();
        if (ListUtils.isExistsEle(companyEmployeeList)) {
            //用户是否已经在该企业中
            boolean userAlreadyJoinCompany = companyEmployeeList.stream().filter(d -> d.getCompanyId().equals(companyId)).count() > 0;
            BooleanUtils.isTrueThrow(userAlreadyJoinCompany, "您已经加入,请勿重复加入");

            //获取用户加入的所有公司
            List<String> haveJoinedCompanyIdList = companyEmployeeList.stream().map(CompanyEmployee::getCompanyId).distinct().collect(Collectors.toList());
            //查找每个公司下的员工
            for (String forCompanyId : haveJoinedCompanyIdList) {
                List<CompanyEmployee> oneCompanyEmployeeList = baseCompanyEmployeeService.getByCompanyId(forCompanyId);
                if (ListUtils.isExistsEle(oneCompanyEmployeeList)) {
                    //当前用户是不是这家公司的管理员
                    boolean isAdmin = oneCompanyEmployeeList.stream().filter(d -> d.getIsAdmin() && d.getUserId().equals(userId)).count() > 0;
                    //这家公司除了自已有没有其他员工
                    boolean isExistsOtherEmployee = oneCompanyEmployeeList.stream().filter(d -> !d.getUserId().equals(userId)).count() > 0;
                    if (isExistsOtherEmployee && isAdmin) {
                        //存在其它员工并且是管理员
                        BooleanUtils.isTrueThrow(isExistsOtherEmployee, String.format("[%s]存在其它成员,请转交管理员后再加入公司", oneCompanyEmployeeList.get(0).getCompanyName()));
                    } else if (!isExistsOtherEmployee && isAdmin) {
                        //不存在其它员工并且是管理员,该除该公司
                        needDelCompanyIdList.add(forCompanyId);
                    }
                }
            }

            //已存在用户加入的公司
            List<String> alreadyJoincompanyIdList = companyEmployeeList.stream().map(CompanyEmployee::getCompanyId).collect(Collectors.toList());
            for (String alreadyJoincompanyId : alreadyJoincompanyIdList) {
                //把用户从该公司移除
                baseCompanyEmployeeService.delByUserIdAndCompanyIdAndDelOtherBus(userId, alreadyJoincompanyId);
            }
        }

        //加入公司
        CompanyDepartment defaultDepartment = baseCompanyDepartmentService.getByCompanyIdAndCompanyDepartmentName(companyId, LocalConstant.DEFAULT_DEPARTMENT_NAME, null);
        if (defaultDepartment == null) {
            defaultDepartment = baseCompanyDepartmentService.createDefaultDepartment(companyId);
        }

        //删除公司
        if (ListUtils.isExistsEle(needDelCompanyIdList)) {
            for (String forCompanyId : needDelCompanyIdList) {
                baseCompanyService.delNotInformUserByCompanyId(forCompanyId);
            }
        }
        baseCompanyDepartmentEmployeeService.joinCompany(companyId, AppUtils.getUserId(), defaultDepartment.getCompanyDepartmentId(), StringUtils.EMPTY, false);
        if (ListUtils.isExistsEle(needDelCompanyIdList)) {
            //刷新redis缓存
            baseCompanyService.updateRedisAllCompany();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void userLoginAfterCreateCompany(
            CompanyMapstruct.UserRegisterNewCompanySaveVo vo
    ) {
        String userId = AppUtils.getUserId();
        User user = baseUserService.getById(userId);
        ObjectUtils.isNullThrow(user, ErrMsgConstant.USER_INFO_NOT_EXISTS);

        SpringBootValidateUtils.validate(vo, UserMapstruct.VdRegisterNewCompany.class);
        //验证用户是否已经加入其它公司,如果加入其它公司则需要移除,后再创建新公司
        List<CompanyEmployee> companyEmployeeList = baseCompanyEmployeeService.getByUserId(userId, null);
        if (ListUtils.isExistsEle(companyEmployeeList)) {
            for (CompanyEmployee companyEmployee : companyEmployeeList) {
                Boolean isAdmin = companyEmployee.getIsAdmin();
                BooleanUtils.isTrueThrow(isAdmin, String.format("您是[%s]公司的管理员,请转交管理员后再创建新公司", companyEmployee.getCompanyName()));
            }
            //已存在用户加入的公司
            List<String> companyIdList = companyEmployeeList.stream().map(CompanyEmployee::getCompanyId).collect(Collectors.toList());
            for (String companyId : companyIdList) {
                //把用户从该公司移除
                baseCompanyEmployeeService.delByUserIdAndCompanyIdAndDelOtherBus(userId, companyId);
            }
        }
        //注册新公司
        Company company = baseCompanyService.addUserCompany(user, vo);
        String companyId = company.getCompanyId();

        CompanyDepartment defaultDepartment = baseCompanyDepartmentService.getByCompanyIdAndCompanyDepartmentName(companyId, LocalConstant.DEFAULT_DEPARTMENT_NAME, null);
        if (defaultDepartment == null) {
            defaultDepartment = baseCompanyDepartmentService.createDefaultDepartment(companyId);
        }

        //加入公司下的默认部门
        baseCompanyDepartmentEmployeeService.joinCompany(companyId, user.getUserId(), defaultDepartment.getCompanyDepartmentId(), StringUtils.EMPTY, false);

        //设置用户为公司管理员
        baseCompanyEmployeeService.lambdaUpdate()
                .eq(CompanyEmployee::getUserId, user.getUserId())
                .eq(CompanyEmployee::getCompanyId, companyId)
                .set(CompanyEmployee::getIsAdmin, true)
                .update();

        //发送事件
        applicationContext.publishEvent(new CompanyEvent(this, company, CompanyEvent.REGISTER_COMPANY));
    }
}